﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AsyncCamera.Camera.media;
using Emgu.CV;
using Emgu.CV.Structure;
using System.Drawing;
using Emgu.CV.VideoSurveillance;
using AForge.Imaging;
using AForge;
using Incendios0_1.Camera.wpfdatamanager;
using AsyncCamera.Camera.Pelco;
using Incendios0_1.localization;
using Incendios0_1.tools;
using Incendios0_1.sms;
using System.Media;

namespace Incendios0_1.Camera.media.filters
{
    class FireSegmentationFilter : MediaFilter
    {
        private Guid sourceId;
        

        public FireSegmentationFilter(MediaSource source)
            : base()
        {
            sourceId = source.GUID;
            plugIn[sourceId] = source;
            lastFrame[sourceId] = source.Frame;
            if (source.Frame != null)
            {
                Tick(null, null);
            }
            else
            {
                frame = null;
            }
        }

        protected override void Tick(object sender, EventArgs e)
        {
            Frame newFrame = plugIn[sourceId].Frame;
            if (newFrame != null && (lastFrame[sourceId] == null || lastFrame[sourceId].Id != newFrame.Id))
            {
                lastFrame[sourceId] = newFrame.Clone();
                Image<Bgr, Byte> bgrImg = lastFrame[sourceId].Image as Image<Bgr, Byte>;
                Image<Gray, Byte> destgray = new Image<Gray, byte>(bgrImg.Size);
                Image<Bgr, Byte> dest = bgrImg.Clone();
                for (int x = 0; x < bgrImg.Size.Width; x++)
                {
                    for (int y = 0; y < bgrImg.Size.Height; y++)
                    {
                        if ((bgrImg.Data[y, x, 2] >= 52) && (bgrImg.Data[y, x, 2] <= 89) &&
                            (bgrImg.Data[y, x, 1] >= 71) && (bgrImg.Data[y, x, 1] <= 141) &&
                            (bgrImg.Data[y, x, 0] >= 91) && (bgrImg.Data[y, x, 0] <= 171))
                            destgray[y, x] = new Gray(255);

                        else
                        {
                            destgray[y, x] = new Gray(0);
                        }
                    }
                }
                BlobCounter bcounter = new BlobCounter(destgray.Bitmap);
                Blob[] blobs = bcounter.GetObjectsInformation();
                /*foreach (Blob blob in blobs)
                {
                    //if (blob.Area >= minarea && blob.Area <= maxarea)
                    dest.Draw(blob.Rectangle,new Bgr(255,255,0),1);
                }*/
                if (blobs.Count() > 0)
                {
                    Blob maxBlob = blobs[0];
                    foreach (Blob blob in blobs)
                    {
                        if (blob.Area > maxBlob.Area)
                            maxBlob = blob;
                    }
                    if (maxBlob.Area > 100)
                    {
                        PelcoCamera cam = AttachedCamera as PelcoCamera;
                        dest.Draw(maxBlob.Rectangle, new Bgr(0, 0, 255), 1);
                        CircleF f = new CircleF(new PointF(maxBlob.CenterOfGravity.X, maxBlob.CenterOfGravity.Y), 5);
                        dest.Draw(f, new Bgr(Color.Aquamarine), 1);
                        if (!AttachedCamera.detectedFire)
                        {
                            if (SerialPortManager.CameraPortOpen)
                            {
                                Vector3 loc = cam.getSphereCoords();
                                Vector3 dir = cam.getDirectionVector();
                                Vector3[] pts = Sphere.SecantIntersection(new Sphere(new Vector3(0, 0, 0), 6371000), new Line(loc, dir));
                                if (pts.Count() <= 0)
                                {
                                    cam.detectedLatitud = null;
                                    cam.detectedLongitud = null;
                                }
                                else
                                {
                                    Vector3 vc = pts[0];
                                    foreach (Vector3 v in pts)
                                    {
                                        double n1 = (v - loc).R;
                                        double n2 = (vc - loc).R;
                                        if (n1 < n2)
                                            vc = v;
                                    }
                                    GeoCoord gc = vc.getGeo();
                                    cam.detectedLatitud = gc.Lat;
                                    cam.detectedLongitud = gc.Long;
                                }
                            }
                            else
                            {
                                cam.detectedLatitud = null;
                                cam.detectedLongitud = null;
                            }
                            AttachedCamera.detectedFire = true;
                            SystemSounds.Asterisk.Play();
                            if (CameraManager.WindowMap.listBox1.Items.IndexOf(AttachedCamera) < 0)
                            {
                                CameraManager.WindowMap.addActiveCamera(AttachedCamera);
                                if (!CameraManager.WindowMap.IsVisible)
                                {
                                    CameraManager.WindowMap.Show();
                                }
                            }
                            if (SerialPortManager.SMSPortOpen)
                            {
                                Contacts[] cs = Contacts.all;
                                SMS_Class sms = new SMS_Class();
                                foreach (Contacts c in cs)
                                {
                                    if (cam.detectedLatitud != null)
                                        sms.sendMsg(c.Phone, "Incendio detectado en Lat:" + String.Format("{0:0.000000}", cam.detectedLatitud) + " Long:" + String.Format("{0:0.000000}", cam.detectedLongitud));
                                    else
                                        sms.sendMsg(c.Phone, "Incendio detectado en Cámara Lat:" + String.Format("{0:0.000000}", cam.Latitud) + " Long:" + String.Format("{0:0.000000}", cam.Longitud));
                                }
                            }
                        }
                    }
                }
                lastFrame[sourceId].Image = dest.Convert<Bgr, Byte>();
                frame = lastFrame[sourceId];
            }
        }
    }
}
